/**
 * 
 */
package com.epart.crypt;

import java.io.UnsupportedEncodingException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

/**
 * @author cwsong
 * @since 2012. 6. 7.
 */
public class EpartCipher {
	
	//private static final String SECRET_KEY = "183a475937405b4759380c3725374d21";
	//private static final String IV_SEED = "26c7d1d26c142de0a3b82f7e8f90860a";
	private static final String SECRET_KEY = "용인";
	private static final String IV_SEED = "초기값";

	private static final String CHARSET = "UTF-8";
	private static final String TRANSFORMATION = "AES/CBC/PKCS5Padding";
	
	private static SecretKeySpec secretKeySpec = null;
	private static IvParameterSpec initialVector = null;
	private static Cipher encryptCipher = null;
	private static Cipher decryptCipher = null;
	
	private static EpartCipher instance = new EpartCipher();
	
	static{
		//secretKeySpec = new SecretKeySpec( Utils.stringToByteArray(SECRET_KEY, 16), "AES"); 
		//initialVector = new IvParameterSpec( Utils.stringToByteArray(IV_SEED, 16)); 
		
		MessageDigest md5;
		try {
			md5 = MessageDigest.getInstance("MD5");
			secretKeySpec = new SecretKeySpec( md5.digest(SECRET_KEY.getBytes("UTF8")), "AES"); 
			initialVector = new IvParameterSpec( md5.digest(IV_SEED.getBytes("UTF8")));
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
	}
	
	public static EpartCipher getInstance(){
		if( instance == null ){
			return new EpartCipher();
		} else {
			return instance;
		}
	}
	
	public Cipher getEncryptCipher() throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchPaddingException{
		if( encryptCipher == null){
			encryptCipher = Cipher.getInstance(TRANSFORMATION);
			encryptCipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, initialVector);
		}
		return encryptCipher;
	}
	
	public Cipher getDecryptCipher() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, InvalidAlgorithmParameterException{
		if( decryptCipher == null ){
			decryptCipher = Cipher.getInstance(TRANSFORMATION);
			decryptCipher.init(Cipher.DECRYPT_MODE, secretKeySpec, initialVector);
		}
		return decryptCipher;
	}
	
	public String encrypt(String cleanStr) throws InvalidKeyException, IllegalStateException, IllegalBlockSizeException, BadPaddingException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchPaddingException, UnsupportedEncodingException{
		byte[] bytes = getEncryptCipher().doFinal(cleanStr.getBytes(CHARSET));
		//return new String(Base64Coder.encode (bytes));
		return Base64Coder.encodeLines(bytes);
	}
	
	public String decrypt(String encryptStr) throws InvalidKeyException, IllegalStateException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidAlgorithmParameterException, UnsupportedEncodingException {
		//byte[] bytes = getDecryptCipher().doFinal( Base64Coder.decode(encryptStr) );
		byte[] bytes = getDecryptCipher().doFinal( Base64Coder.decodeLines (encryptStr) );
		return new String(bytes);
	}
	
	public static void main(String[] args) throws InvalidKeyException, InvalidAlgorithmParameterException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalStateException, IllegalBlockSizeException, BadPaddingException, UnsupportedEncodingException{
		
		
		//byte[] bbb = Utils.stringToByteArray(SECRET_KEY, 16);
		//System.out.println(">>> EpartCipher.main >>>" + bbb.length );
		//for(int i = 0; i<bbb.length; i++){
			//System.out.print( (char) bbb[i] );
		//}
		
		int loop = 1;
		
		long start = System.currentTimeMillis();
		long end = 0L;
		//System.out.println(">>> EpartCipher.main >>>" + start );
		for(int i = 1; i<=loop; i++){
			String original = "qwer12345";
			String encStr = instance.encrypt(original);
			String decStr = instance.decrypt(encStr);
			if( i == loop ){
				//System.out.println(original);
				System.out.println(">>> EpartCipher.main >>>" + encStr);
				System.out.println(">>> EpartCipher.main >>>" + decStr );
			}
		}
		end = System.currentTimeMillis();
		//System.out.println(">>> EpartCipher.main >>>" + end );
		System.out.println((end - start)/1000.000 );
		
		
		//System.out.println(">>> EpartCipher.main >>>" + Base64Coder.decodeString("RvVaeL1L8FvussqPuL1ItA==") );
		/*
		if( args.length <= 1 ){
			throw new IllegalArgumentException("error #1 at least 2 arguemwets");
		}
		if( "-enc".equalsIgnoreCase(args[0]) ){
			System.out.println(instance.encrypt(args[1]));
		} else if( "-dec".equalsIgnoreCase(args[1]) ){
			System.out.println(instance.decrypt(args[1]));
		} else {
			throw new IllegalArgumentException("error #2 not acceptable action -enc or -dec");
		}
		*/
	}
}
